﻿#region License
// Copyright © 2004 - 2010 All Right Reserved, Derek Goslin
// 
// 1. Definitions
// The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under U.S. copyright law.
// A "contribution" is the original software, or any additions or changes to the software.
// A "contributor" is any person that distributes its contribution under this license.
// "Licensed patents" are a contributor's patent claims that read directly on its contribution.
// 
// 2. Grant of Rights
// (A) Copyright Grant- Subject to the terms of this license, including the license
//     conditions and limitations in section 3, each contributor grants you a non-exclusive,
//     worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative 
//     works of its contribution, and distribute its contribution or any derivative works that you create.
// (B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations
//     in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its
//     licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of
//     its contribution in the software or derivative works of the contribution in the software.
// 
// 3. Conditions and Limitations
// (A) Reciprocal Grants- For any file you distribute that contains code from the software (in source code or binary format), 
//     you must provide recipients the source code to that file along with a copy of this license, which license will govern that file. 
//     You may license other files that are entirely your own work and do not contain code from the software under any terms you choose.
// (B) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks.
// (C) If you bring a patent claim against any contributor over patents that you claim are infringed by the software,
//     your patent license from such contributor to the software ends automatically.
// (D) If you distribute any portion of the software, you must retain all copyright, patent, trademark,
//     and attribution notices that are present in the software.
// (E) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy 
//     of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do 
//     so under a license that complies with this license.
// (F) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions.
//    You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your
//    local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement.
#endregion

using System;
using System.IO;
using System.IO.Compression;
using System.Resources;
using System.Text;
using System.Xml;

namespace CompressResources
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            foreach (String s in args)
            {
                Console.WriteLine(s);
            }

            String resourceFilesPath = args[0];
            String resourceFileExtension = args[1];
            String resourceFileTarget = args[2];
            String defaultLang = args[3];
            String outputFolder = args[4];

            try
            {
                foreach (string folder in Directory.GetDirectories(resourceFilesPath))
                {
                    var lang = folder.Replace(resourceFilesPath, "");

                    String targetResourceFile;
                    if(lang != defaultLang)
                    {
                        targetResourceFile = String.Format("{0}{1}{2}{3}{4}", outputFolder, resourceFileTarget, ".", lang, ".resx");
                    }
                    else
                    {
                        targetResourceFile = String.Format("{0}{1}{2}", outputFolder, resourceFileTarget, ".resx");
                    }

                    if (File.Exists(targetResourceFile))
                    {
                        File.SetAttributes(targetResourceFile, FileAttributes.Normal);
                        File.Delete(targetResourceFile);
                    }

                    string searchFileExtension;

                    if (!resourceFileExtension.Contains("*."))
                    {
                        searchFileExtension = "*." + resourceFileExtension.Replace(".","");
                    }
                    else
                    {
                        searchFileExtension = resourceFileExtension;
                    }

                    var files = Directory.GetFiles(folder, searchFileExtension);

                    if (files.Length != 0)
                    {
                        Int32 i = 1;

                        var builder = new StringBuilder();

                        Console.WriteLine("Adding resources to {0}", targetResourceFile);

                        using (var rw = new ResXResourceWriter(targetResourceFile))
                        {
                            using (var writer = XmlWriter.Create(builder))
                            {
                                writer.WriteStartElement("EcuDescriptors");
                                writer.WriteStartElement("Descriptors");
                                
                                foreach (var file in files)
                                {
                                    String xmlContent;
                                    using (var sr = new StreamReader(file))
                                    {
                                        xmlContent = sr.ReadToEnd();
                                    }

                                    string model;
                                    string type;

                                    RetrieveModelAndType(xmlContent, out model, out type);

                                    writer.WriteStartElement("EcuDescriptor");
                                    writer.WriteElementString("Name", model);
                                    writer.WriteElementString("EcuType", type);
                                    writer.WriteEndElement();

                                    rw.AddResource(i++.ToString(), CompressContent(xmlContent));
                                }

                                writer.WriteEndElement();
                                writer.WriteEndElement();
                            }

                            rw.AddResource("EcuDescriptors", builder.ToString());
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine(e.ToString());
            }
        }

        private static void RetrieveModelAndType(string content, out string model, out string type)
        {
            var document = new XmlDocument();
            document.LoadXml(content);
            XmlNodeList modelNodes = document.GetElementsByTagName("Model");

            model = modelNodes[0].InnerText;
            type = document.DocumentElement.Name;
        }

        private static byte[] CompressContent(String content)
        {
            byte[] compressedBuffer;
            var e = Encoding.UTF8;

            byte[] rawBuffer = e.GetBytes(content);

            using (var ms = new MemoryStream())
            {
                var compressedzipStream = new DeflateStream(ms, CompressionMode.Compress, true);
                compressedzipStream.Write(rawBuffer, 0, rawBuffer.Length);
                compressedzipStream.Close();

                compressedBuffer = new byte[ms.Length];
                ms.Position = 0;
                ms.Read(compressedBuffer, 0, compressedBuffer.Length);
            }

            float ratio = compressedBuffer.Length/(float) rawBuffer.Length * 100;
            Console.WriteLine("Original size: {0}, Compressed size: {1} Compression Ratio {2}", rawBuffer.Length, compressedBuffer.Length, ratio);

            return compressedBuffer;
        }
    }
}